package com.example.demo.yjcx.service;

import com.example.demo.service.DeliveryPriceConfig;
import com.example.demo.utils.BigDecimalCollector;
import com.example.demo.utils.BigDecimalUtils;
import com.example.demo.yjcx.BasePriceTypeEnum;
import com.example.demo.yjcx.CurrencyEnum;
import com.example.demo.yjcx.FeeItemTypeEnum;
import com.example.demo.yjcx.dao.AreaFeeItem;
import com.example.demo.yjcx.dao.BasePriceDO;
import com.example.demo.yjcx.model.YJCalculateResult;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author linjingze
 * @date 2023/12/21 3:48 PM
 */
@Service
public class YJCalculateService {

    @Autowired
    private BasePriceService basePriceService;

    @Autowired
    private AreaFeeItemService areaFeeItemService;

    public List<YJCalculateResult> calculate(String warehouse) {
        List<BasePriceDO> basePriceList = basePriceService.listBasePrice();
        if (CollectionUtils.isEmpty(basePriceList)) {
            throw new RuntimeException("未配置运价查询信息");
        }

        Map<String, BasePriceDO> basePriceMap = basePriceList.stream()
                .collect(Collectors.toMap(BasePriceDO::getType, Function.identity()));
        BasePriceDO hl = basePriceMap.get(BasePriceTypeEnum.HL.name());
        if (hl == null) {
            throw new RuntimeException("未配置汇率");
        }
        BasePriceDO hs = basePriceMap.get(BasePriceTypeEnum.HS.name());
        if (hs == null) {
            throw new RuntimeException("未配置以多少核算");
        }
        List<AreaFeeItem> areaFeeItems = areaFeeItemService.listFeeItemByWarehouse(warehouse);
        if (CollectionUtils.isEmpty(areaFeeItems)) {
            return Collections.emptyList();
        }
        Map<String, List<AreaFeeItem>> map = areaFeeItems.stream().collect(Collectors.groupingBy(AreaFeeItem::getArea));
        List<YJCalculateResult> results = new ArrayList<>(map.size());
        for (Map.Entry<String, List<AreaFeeItem>> e : map.entrySet()) {
            String area = e.getKey();
            BasePriceDO hyf = basePriceMap.get(BasePriceTypeEnum.getBasePriceType(area));
            if (hyf == null) {
                throw new RuntimeException("未配置" + area + "海运费");
            }

            YJCalculateResult yjCalculateResult = calculateOnArea(e.getValue(),
                    new BigDecimal(hyf.getPrice()), new BigDecimal(hl.getPrice()), new BigDecimal(hs.getPrice()),
                    new BigDecimal(2), new BigDecimal(167), new BigDecimal("0.5"), new BigDecimal(69));
            yjCalculateResult.setArea(area);
            yjCalculateResult.setZcjg(DeliveryPriceConfig.getFullCarPrice(area, warehouse));
            results.add(yjCalculateResult);
        }
        return results;
    }

    public YJCalculateResult calculateByArea(String area) {
        List<BasePriceDO> basePriceList = basePriceService.listBasePrice();
        if (CollectionUtils.isEmpty(basePriceList)) {
            throw new RuntimeException("未配置运价查询信息");
        }

        Map<String, BasePriceDO> basePriceMap = basePriceList.stream()
                .collect(Collectors.toMap(BasePriceDO::getType, Function.identity()));
        BasePriceDO hl = basePriceMap.get(BasePriceTypeEnum.HL.name());
        if (hl == null) {
            throw new RuntimeException("未配置汇率");
        }
        BasePriceDO hs = basePriceMap.get(BasePriceTypeEnum.HS.name());
        if (hs == null) {
            throw new RuntimeException("未配置以多少核算");
        }
        List<AreaFeeItem> areaFeeItems = areaFeeItemService.listFeeItemByArea(Collections.singletonList(area));
        if (CollectionUtils.isEmpty(areaFeeItems)) {
            return null;
        }
        BasePriceDO hyf = basePriceMap.get(BasePriceTypeEnum.getBasePriceType(area));
        if (hyf == null) {
            throw new RuntimeException("未配置" + area + "海运费");
        }

        YJCalculateResult yjCalculateResult = calculateOnArea(areaFeeItems,
                new BigDecimal(hyf.getPrice()), new BigDecimal(hl.getPrice()), new BigDecimal(hs.getPrice()),
                new BigDecimal(2), new BigDecimal(167), new BigDecimal("0.5"), new BigDecimal(69));
        yjCalculateResult.setArea(area);
        return yjCalculateResult;
    }


    public YJCalculateResult calculateOnArea(List<AreaFeeItem> areaFeeItems,
                                             BigDecimal hyfUsd,
                                             BigDecimal hl,
                                             BigDecimal hs,
                                             BigDecimal tptj,
                                             BigDecimal cjz,
                                             BigDecimal bssj,
                                             BigDecimal hq40Vol) {
        // 前段+后段总人民币
        BigDecimal allCnySum = BigDecimal.ZERO;
        for (AreaFeeItem areaFeeItem : areaFeeItems) {
            if (!FeeItemTypeEnum.isQianHouDuanType(areaFeeItem.getType())) {
                continue;
            }
            BigDecimal price = new BigDecimal(areaFeeItem.getPrice());
            if (CurrencyEnum.isUSD(areaFeeItem.getCurrency())) {
                price = BigDecimalUtils.mul(price, hl);
            }
            if ("托架费Chassis Rental".equals(areaFeeItem.getFeeName())) {
                price = BigDecimalUtils.mul(price, new BigDecimal(5));
            }
            if ("打托费".equals(areaFeeItem.getFeeName())) {
                price = BigDecimalUtils.mul(price, new BigDecimal(39));
            }
            System.out.println(areaFeeItem.getFeeName()+"="+BigDecimalUtils.toPlainString(price));
            allCnySum = BigDecimalUtils.add(allCnySum, price);
        }
        allCnySum = BigDecimalUtils.add(allCnySum, BigDecimalUtils.mul(hyfUsd, hl));
        BigDecimal allUsdSum = BigDecimalUtils.div(allCnySum, hl);

        BigDecimal weightPrice = BigDecimalUtils.div(allCnySum, hs);
        BigDecimal volumePrice = BigDecimalUtils.div(allCnySum, hq40Vol);

        BigDecimal ckFeeAmount = areaFeeItems.stream().filter(s -> FeeItemTypeEnum.isCK(s.getType()))
                .map(s -> new BigDecimal(s.getPrice())).collect(BigDecimalCollector.toSum());

        YJCalculateResult yjCalculateResult = new YJCalculateResult();
        yjCalculateResult.setAllUsd(allUsdSum);
        yjCalculateResult.setAllCny(allCnySum);
        yjCalculateResult.setVolumePrice(volumePrice);
        yjCalculateResult.setWeightPrice(BigDecimalUtils.add(weightPrice, bssj));
        BigDecimal psfPrice = BigDecimalUtils.div(BigDecimalUtils.mul(ckFeeAmount, hl), tptj);
        yjCalculateResult.setPsf(psfPrice);
        yjCalculateResult.setDbjg(ckFeeAmount);
        yjCalculateResult.setHyf(hyfUsd);
        yjCalculateResult.setLfcb(BigDecimalUtils.roundToNearestTen(BigDecimalUtils.add(psfPrice, volumePrice)));
        yjCalculateResult.setBsgjcb(BigDecimalUtils.add(BigDecimalUtils.div(psfPrice, cjz), weightPrice, bssj).setScale(1, RoundingMode.HALF_UP));
        return yjCalculateResult;
    }
}
